/**   
 * @Title: MyRealm.java
 * @Package com.nbst.config.shiro
 * @Description:
 * @author King  
 * @date 2018-8-29  
 */

package com.nbst.shiro;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

import com.nbst.comnutil.DESUtil;
import com.nbst.comnutil.LogOut;
import com.nbst.comnutil.StringUtil;
import com.nbst.dao.mapper.mes.ButtonMapper;
import com.nbst.dao.mapper.mes.MenuMapper;
import com.nbst.dao.mapper.mes.RoleMapper;
import com.nbst.dao.mapper.mes.UserMapper;
import com.nbst.model.base.User;

/**
 * @ClassName: MyRealm
 * @Description:自定义ShiroRealm
 * @author King
 * @date 2018-8-29
 * 
 */

public class MyRealm extends AuthorizingRealm {
	@Autowired
	UserMapper userMapper;// 用户

	@Autowired
	MenuMapper menuMapper;// 页面权限

	@Autowired
	RoleMapper roleMapper;// 角色

	@Autowired
	ButtonMapper buttonMapper;// 按钮权限

	@Autowired
	LogOut logout;

	/**
	 * 执行授权逻辑
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		System.out.println("执行授权逻辑。。。");

		// 给资源进行授权
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

		User user = (User) SecurityUtils.getSubject().getPrincipal();
		// 1.先找出用户
		Map<String, Object> map = new HashMap<>(3);
		map.put("account", user.getAccount());
		User dUser = userMapper.findByCondition(map).get(0);
		// 2.再找出用户所拥有的角色
		Set<String> roles = new HashSet<String>();
		map.clear();
		List<String> list = roleMapper.getUserRolesName(dUser.getId());
		for (String role : list) {
			roles.add(role);
		}
		// 3.再找出该用户所拥有的页面权限
		List<String> menus = menuMapper.getUserMenuName(dUser.getId());
		for (String menu : menus) {
			info.addStringPermission(menu);
		}

		// 4.再找出该用户所拥有的按钮权限
		List<String> buttonUrl = buttonMapper.getUserRoleButtonUrl(dUser.getId());
		for (String button : buttonUrl) {
			info.addStringPermission(button);
		}

		info.setRoles(roles);
		return info;
	}

	/**
	 * 执行认证逻辑
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		// SecurityUtils.getSubject().getSession().setTimeout(86400000);
		// 编写shiro判断逻辑，判断用户名和密码
		// 1.判断用户名
		UsernamePasswordToken utoken = (UsernamePasswordToken) token;
		Integer cardLoginflag = 0;// 刷卡登录
		Map<String, Object> map = new HashMap<>(8);
		map.put("account", utoken.getUsername());
		List<User> list = userMapper.findByCondition(map);
		if (!StringUtil.isEmpty(utoken.getHost())) {
			// 如果为空则说明
			if (list.size() == 0) {
				map.clear();
				map.put("userCode", utoken.getUsername());
				list = userMapper.findByCondition(map);
				cardLoginflag = 1;
				if (list.size() > 0) {
					list.get(0).setRemark("bgt");
				}

			}
		}
		if (list.size() == 0) {
			return null;
		}
		if (list.size() == 1) {
			logout.info("用户[" + list.get(0).getName() + "]正在尝试登陆系统...");
			if (list.get(0).getErpUserId() == null) {
				list.get(0).setErpUserId(16394);
			}
			if (list.get(0).getfStop() == 0) {
				throw new DisabledAccountException("该帐号已停用");
			}

			// 再查询报工台的角色
			if ("admin".equals(list.get(0).getName()) || "system".equals(list.get(0).getName())) {
				list.get(0).setBgtRole("1");
			} else {
				if (list.get(0).getBgtRole() != null) {

					if (list.get(0).getBgtRole().contains("28")) {
						// 28操作工报工台
						list.get(0).setBgtRole("1");
					} else if (list.get(0).getBgtRole().contains("29")) {
						list.get(0).setBgtRole("2");
					}

				}
			}
			SimpleAuthenticationInfo info;
			// 如果只有一条数据则把这条数据的对象也放入shiro
			if (!StringUtil.isEmpty(utoken.getHost())) {
				// 如果host不为空则说明是扫码登录，那么就不需要验证密码
				info = new SimpleAuthenticationInfo(list.get(0), DESUtil.encrypt(null), getName());
			} else {
				// 如果host为空则说明是正常登录
				info = new SimpleAuthenticationInfo(list.get(0), list.get(0).getPassword(), getName());

			}
			Subject currentUser = SecurityUtils.getSubject();
			Session session = currentUser.getSession();
			session.setAttribute("user", list.get(0));
			if (cardLoginflag == 1) {
				// 如果是报工台刷卡登录则将session过期时间设为5分钟
				SecurityUtils.getSubject().getSession().setTimeout(300000);
			} else {
				// 不是则设置为8小时
				SecurityUtils.getSubject().getSession().setTimeout(28800000);
			}
			return info;
		} else {
			throw new DisabledAccountException("绑定该卡号的用户超过1个，系统无法判定登录哪个帐号，无法登录");

		}
	}

	/**
	 * 清空权限缓存的方法，一般在修改权限方法的最后调用
	 * 
	 * void
	 * 
	 * @author King
	 * @date 2018-9-6
	 */
	public void clearAuthz() {
		this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
	}
}
